iT邦幫忙

2021 iThome 鐵人賽

DAY 18
0

這是個工具半殘時,debug會很慘烈的故事Orz
既上次想要搬遷到host來用qemu-user加快測試節奏後,發現Alpine內的toolchain與host的,因為bintuils版本不一,導致DWARF2的資訊無法被host端解讀,而沒辦法正常判讀行號與位置。

幾經嘗試,最後決定重新在 host 端使用riscv-gnu-toolchain,在configure時,多加上 --enable-gdb 來開啟gdb的support。在有了可用的gdb後,繼續進行debug,
從debug 訊息中判讀,得知程式是在清零 bss section時,memset()遇上存取系統認為不可存取的區域:

│   780                         if (ph->p_memsz > ph->p_filesz && (ph->p_flags&PF_W)) {         
│   781                                 size_t brk = (size_t)base+ph->p_vaddr+ph->p_filesz;     
│   782                                 size_t pgbrk = brk+PAGE_SIZE-1 & -PAGE_SIZE;            
│  >783                                 memset((void *)brk, 0, pgbrk-brk & PAGE_SIZE-1);        
│   784                                 if (pgbrk-(size_t)base < this_max && mmap_fixed((void *)
│   785                                         goto error;                                     
│   786                         }                                                               
│   787                 }                                                                       
│   788                 for (i=0; ((size_t *)(base+dyn))[i]; i+=2)                              
└───────────────────────────────────────────────────────────────────────────────────────────────
remote Thread 1.243523 In: map_library                                                          
(gdb) down
#1  0x3f7b1b94 in map_library (fd=5, dso=0x3fffe458) at ldso/dynlink.c:783
(gdb) p base
$1 = (unsigned char *) 0x3f423000 "\177ELF\001\001\001"
(gdb) p/x ph->p_vaddr
$2 = 0x279a50
(gdb) p/x brk
$3 = 0x3f6c7708

其中這時可以開始懷疑是不是mmap的部份有出狀況,於是一路step進去看,此時發現我們呼叫到了mmap:

│   28          #ifdef SYS_mmap2                                                              
│   29                  ret = __syscall(SYS_mmap2, start, len, prot, flags, fd, off/UNIT);    
│   30          #else                                                                         
│  >31                  ret = __syscall(SYS_mmap, start, len, prot, flags, fd, off);          
│   32          #endif                                                                        
│   33                  /* Fixup incorrect EPERM from kernel. */                              
│   34                  if (ret == -EPERM && !start && (flags&MAP_ANON) && !(flags&MAP_FIXED))
│   35                          ret = -ENOMEM;                                                
│   36                  return (void *)__syscall_ret(ret);                                    
│   37          }                                                                             
└─────────────────────────────────────────────────────────────────────────────────────────────
remote Thread 1.244285 In: __mmap                                                             
(gdb) ni

這時,我們回去對一下QEMU的linux-user/riscv/syscall32_nr.h

208 #define TARGET_NR_mmap2 222

這下,就有趣了。

這時我們來看一下mmap2的manual page:

The mmap2() system call provides the same interface as mmap(2), except that the final argument specifies the offset into the file in 4096-byte units
       (instead of bytes, as is done by mmap(2)).  This enables applications that use a 32-bit off_t to map large files (up to 2^44 bytes).

而目前我的musl source中,SYS_mmap被指向了mmap2,變成錯的syscall symbol,被對上mmap2。
這點改正後,我們可以再繼續作驗證看看。


上一篇
Alpine Linux Porting (一點五?)
下一篇
Alpine Linux Porting (一點七?)
系列文
Port Alpine Linux to open source RISC-V platform30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言